//
//  ETH+Account+BIP39.swift
//  XHWalletUtils
//
//  Created by xinph on 2020/5/16.
//  Copyright © 2020 xinph. All rights reserved.
//

import Foundation

extension ETH : BIP39 {
    public static func importWalletFromMne(_ path: String?, password: String, name: String?, mnemonics: String) -> coswift.Promise<Wallet> {
        let promise = coswift.Promise<Wallet>()
        
        let keystore: BIP32Keystore
        let keyData: Data
        do {
            if let path = path {
                keystore = try BIP32Keystore(
                    mnemonics: mnemonics,
                    password: password,
                    mnemonicsPassword: "",
                    language: .english,
                    prefixPath: path)!
            } else {
                keystore = try BIP32Keystore(
                    mnemonics: mnemonics,
                    password: password,
                    mnemonicsPassword: "",
                    language: .english)!
            }
            keyData = try JSONEncoder().encode(keystore.keystoreParams)
        } catch {
            promise.reject(error: XHError(mnemonicsError))
            return promise
        }
        let name = name ?? "Wallet ETH"
        let address = keystore.addresses!.first!.address
        let account = Account(name, address: address, coin: 60)
        
        var privateKey = ""
        var publicKey = ""
        let wallet = ETH(mnemonics, keystore: keyData, path: CoinBIP44.defaultETHPath, isHD: true, privateKey: privateKey, publicKey: publicKey)

        co_launch {
            let result = try await(promise: wallet.UNSAFE_getPrivateAndPublicKey(password: password, address: address))
            switch result {
            case let .fulfilled(key):
                wallet.privateKey = key.pri
                wallet.publicKey = key.pub
                Manager.IO.writeWallet(account, wallet: wallet)
                _ = wallet.generateWeb3()
                promise.fulfill(value: wallet)
            default: break
            }
        }
        return promise
    }
    
    public static func createAccountByMnemonics(_ password: String, name: String) -> coswift.Promise<WalletType> {
        let promise = coswift.Promise<WalletType>()

        let password = password
        let bitsOfEntropy: Int = 128 // Entropy is a measure of password strength. Usually used 128 or 256 bits.
        let mnemonics: String
        do {
            mnemonics = try web3swift.BIP39.generateMnemonics(bitsOfEntropy: bitsOfEntropy)!
        } catch {
            promise.reject(error: XHError(createWalletFailure))
            return promise
        }
        let keystore: BIP32Keystore
        let keyData: Data
        do {
            keystore = try BIP32Keystore(
                mnemonics: mnemonics,
                password: password,
                mnemonicsPassword: "",
                language: .english)!
            keyData = try JSONEncoder().encode(keystore.keystoreParams)
        } catch {
            promise.reject(error: (XHError(createWalletFailure)))
            return promise
        }
        let name = name.isEmpty ? "Wallet ETH" : name
        let address = keystore.addresses!.first!.address
        let account = Account(name, address: address, coin: 60)
        var privateKey = ""
        var publicKey = ""
        let wallet = ETH(mnemonics, keystore: keyData, path: "", isHD: true, privateKey: privateKey, publicKey: publicKey)

        co_launch {
            let result = try await(promise: wallet.UNSAFE_getPrivateAndPublicKey(password: password, address: address))
            switch result {
            case let .fulfilled(key):
                wallet.privateKey = key.pri
                wallet.publicKey = key.pub
                Manager.IO.writeWallet(account, wallet: wallet)
                _ = wallet.generateWeb3()
                promise.fulfill(value: wallet)
            default: break
            }
        }
        return promise
    }
    
    public static
    func importAccountByMnemonics(_ password: String, name: String, mnemonics: String, saveToLocal: Bool) -> coswift.Promise<WalletType> {
        let promise = coswift.Promise<WalletType>()

        guard !mnemonics.isEmpty, mnemonics.split(separator: " ").count >= 12 else {
            promise.reject(error: XHError(mnemonicsLengthError))
            return promise
        }
        let keystore: BIP32Keystore
        let keyData: Data
        do {
            keystore = try BIP32Keystore(
                mnemonics: mnemonics,
                password: password,
                mnemonicsPassword: "",
                language: .english)!
            keyData = try JSONEncoder().encode(keystore.keystoreParams)
        } catch {
            promise.reject(error: XHError(mnemonicsError))
            return promise
        }
        let name = name.isEmpty ? "Wallet ETH" : name
        let address = keystore.addresses!.first!.address
        let account = Account(name, address: address, coin: 60)
        
        var privateKey = ""
        var publicKey = ""
        let wallet = ETH(mnemonics, keystore: keyData, path: CoinBIP44.defaultETHPath, isHD: true, privateKey: privateKey, publicKey: publicKey)

        co_launch {
            let result = try await(promise: wallet.UNSAFE_getPrivateAndPublicKey(password: password, address: address))
            switch result {
            case let .fulfilled(key):
                wallet.privateKey = key.pri
                wallet.publicKey = key.pub
                Manager.IO.writeWallet(account, wallet: wallet)
                _ = wallet.generateWeb3()
                promise.fulfill(value: wallet)
            default: break
            }
        }
        return promise
    }
}
